/*
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 *
 * HipNetPackets.h
 * Datagram definitions for HipNet, the Hideously Inadequate Protocol
 * Copyright (C) 2005-2009 Simon Newton
 */

#ifndef PLUGINS_HIPNET_HIPNETPACKETS_H_
#define PLUGINS_HIPNET_HIPNETPACKETS_H_

#include <sys/types.h>
#include <stdint.h>
#include <netinet/in.h>

#include "ola/BaseTypes.h"

namespace ola {
namespace plugin {
namespace hipnet {

enum hipnet_packet_type_e {
  HIPNET_PING = 'H' << 24 | 'I' << 16 | 'P' << 8 | 'P',
  HIPNET_PONG = 'H' << 24 | 'I' << 16 | 'P' << 8 | 'Y',
  HIPNET_DMX = 'H' << 24 | 'I' << 16 | 'P' << 8 | 'D',
}__attribute__((packed));

typedef enum hipnet_packet_type_e hipnet_packet_type_t;

/*
 * our ping packet
 */
struct hipnet_ping_s {
  uint32_t head;        // 'HIPP'
  uint8_t  srcnode;     // node type $00 is from controller, $01 is from node
  uint8_t  universe;   // $00 > $FF (the xlr we are talking with)
  uint8_t  mode;        // $00 = expect to rx a pong with mode $01 (xlr is alive)
                                 // $F0 = Configure device to OUTPUT mode (xlr is sending dmx) (default)
                                 // $F1 = Configure device to INPUT mode (xlr is receiving dmx)
} __attribute__((packed));

typedef struct hipnet_ping_s hipnet_ping_t;

/*
 * ping reply, only sent in response to ping
 */
struct hipnet_pong_s {
  uint32_t head;        // 'HIPY'
  uint8_t srcnode;     // node type $00 is from controller, $01 is from node
  uint8_t  universe;   // $00 > $FF (the xlr we are talking with)
  uint8_t  mode;        // $01 = Alert controller we are alive (xlr is alive)  (pong)
                                 // $F0 = Device is in OUTPUT mode (xlr is sending dmx) (default)
                                 // $F1 = Device is in INPUT mode (xlr is receiving dmx)
} __attribute__((packed));

typedef struct hipnet_pong_s    hipnet_pong_t;

/*
 * hipnet data packet 
 */
struct hipnet_data_s {
  uint32_t head;         // 'HIPD'
  uint8_t srcnode;      // node type $00 is from controller, $01 is from node
  uint8_t  universe;    // $00 > $FF (the xlr we are talking with)  
  uint8_t  mode;        // $00  - DMX OUT Frame (as to output to xlr)
                                 //  $01 - DMX/RDM IN Frame (as received from xlr)
                                 //  $F1 - RDM Discovery OUT Frame
                                 //         -  If in OUTPUT mode, interleave this request with DMX output
                                 //         -  breifly turns line around and listens for a response
                                 //  $FF - returned with no data if no response was received to a Discovery OUT frame                                                                            
  uint16_t size;         // size of the data segment
  uint8_t  start;        // START code
  uint8_t  data[DMX_UNIVERSE_SIZE];
} __attribute__((packed));

typedef struct hipnet_data_s    hipnet_data_t;

/*
 * union of all hipnet packets
 */
typedef union {
  hipnet_ping_t ping;
  hipnet_pong_t pong;
  hipnet_data_t dmx;
} hipnet_packet_union_t;
}  // hipnet
}  // plugin
}  // ola
#endif  // PLUGINS_HIPNET_HIPNETPACKETS_H_
